/************************ (C) COPYLEFT 2018 Merafour *************************

* File Name          : cledMatrix.h
* Author             : Merafour
* Last Modified Date : 01/10/2019
* Description        : cled Matrix.
********************************************************************************
* https://merafour.blog.163.com
* merafour@163.com
* https://github.com/merafour
******************************************************************************/
#ifndef _CRGB_MATRIX_H_
#define _CRGB_MATRIX_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdint.h>
#include <stddef.h>

//#include "BRGB.h"

//enum MatrixType_t { 
//	HORIZONTAL_MATRIX = 0,         // 横向
//    VERTICAL_MATRIX = 1,           // 纵向
//    HORIZONTAL_ZIGZAG_MATRIX = 2,  // 横向 Z字型
//    VERTICAL_ZIGZAG_MATRIX = 3     // 纵向 Z字形
//};
#define HORIZONTAL_MATRIX 0            // 横向
#define VERTICAL_MATRIX   1            // 纵向
#define HORIZONTAL_ZIGZAG_MATRIX   2   // 横向 Z字型
#define VERTICAL_ZIGZAG_MATRIX     3   // 纵向 Z字形

// 定义矩阵类型, 根据实际 LED阵列定义
#define MATRIX_TYPE       HORIZONTAL_MATRIX
// 矩阵反向扫描
#define MATRIX_SCAN_XINV   1
#define MATRIX_SCAN_YINV   1
#undef  MATRIX_SCAN_XINV
#undef  MATRIX_SCAN_YINV

// 键盘定义
#define LEDMatrixMode_Simulator   0x00    // 模拟器
#define LEDMatrixMode_K104        0x01    // 104键盘
#define LEDMatrixMode_NUM         0x02    // 17键数字小键盘
#define LEDMatrixMode_PWM         0x03    // PWM模式刷新LED测试矩阵
#define LEDMatrixMode_K104_PWM    0x04    // PWM模式刷新 104键盘
#define LEDMatrixMode_MUSIC       0x05    // 音乐灯光
#define LEDMatrixMode_4X32A       0x06    // 4*32 RGB 矩阵
#define LEDMatrixMode_PWM8X14     0x07    // 8*14 模拟 PWM RGB 矩阵
#define LEDMatrixMode_MEGACUBE8   0x08    // 8个点光立方

//#define LEDMatrixMode             LEDMatrixMode_PWM
//#define LEDMatrixMode             LEDMatrixMode_K104_PWM
//#define LEDMatrixMode             LEDMatrixMode_4X32A
//#define LEDMatrixMode             LEDMatrixMode_PWM8X14
#define LEDMatrixMode             LEDMatrixMode_Simulator

#define  LED_CS_MAX        28
//#define  LED_CS_MAX        8
#if defined(LEDMatrixMode_K104_PWM)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_K104_PWM)    // PWM模式刷新 104键盘
#undef   LED_CS_MAX       
#define  LED_CS_MAX 26
#endif
#if defined(LEDMatrixMode_4X32A)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_4X32A)          // PWM 4*32矩阵灯
#undef   LED_CS_MAX       
#define  LED_CS_MAX 32
#endif
#if defined(LEDMatrixMode_PWM8X14)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_PWM8X14)      // 8*14 模拟 PWM RGB 矩阵
#undef   LED_CS_MAX       
#define  LED_CS_MAX 14
#endif
#if defined(LEDMatrixMode_MEGACUBE8)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_MEGACUBE8)  // 8个点光立方
#undef   LED_CS_MAX       
#define  LED_CS_MAX 32
#endif

//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127	
//[1]0 1 2 3 ... 127	
//[2]0 1 2 3 ... 127	
//[3]0 1 2 3 ... 127	
//[4]0 1 2 3 ... 127	
//[5]0 1 2 3 ... 127	
//[6]0 1 2 3 ... 127	
//[7]0 1 2 3 ... 127 
/********************************************
------------> x+(WIDTH)
|
|
|
y+ (HEIGHT)
******************************************/
#if defined(LEDMatrixMode_K104)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_K104)    // 104键盘
#define  LEDMatrixWidth   21
#define  LEDMatrixHeight  6
//--#define MATRIX_SCAN_XINV   1
// 定义乘法运算用于节约算力
#define  MultipLEDMatrixWidth(y) (((y)<<4)+((y)<<2)+(y))   // y*21 = y*(16+4+1) = (y<<4) + (y<<2) + y
#define  MultipLEDMatrixHeight(x) (((x)<<2) + ((x)<<1))    // x*6  = x*(4+2) = (x<<2) + (x<<1)
#elif defined(LEDMatrixMode_Simulator)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_Simulator)    // 模拟器
#define  LEDMatrixWidth   41
#define  LEDMatrixHeight  41
//--#define MATRIX_SCAN_XINV   1
// 定义乘法运算用于节约算力
#define  MultipLEDMatrixWidth(y)  ((y)*LEDMatrixHeight)   // y*21 = y*(16+4+1) = (y<<4) + (y<<2) + y
#define  MultipLEDMatrixHeight(x) ((x) *LEDMatrixWidth)    // x*6  = x*(4+2) = (x<<2) + (x<<1)
#elif defined(LEDMatrixMode_NUM)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_NUM)    // 数字小键盘
#define MATRIX_SCAN_XINV   1
#define  LEDMatrixWidth   4
#define  LEDMatrixHeight  5
// 定义乘法运算用于节约算力
#define  MultipLEDMatrixWidth(y) ((y)<<2)                  // y*4 = (y<<2)
#define  MultipLEDMatrixHeight(x) (((x)<<2) + (x))          // x*5  = x*(4+1) = (x<<2) + (x)
#elif defined(LEDMatrixMode_PWM)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_PWM)    // PWM模式刷新LED测试矩阵
#define  LEDMatrixWidth   28
#define  LEDMatrixHeight  4
// 定义乘法运算用于节约算力
#define  MultipLEDMatrixWidth(y) (((y)<<4)+((y)<<3)+((y)<<2))                  // y*28 = y*(16+8+4) = (y<<4)+(y<<3)+(y<<2)
#define  MultipLEDMatrixHeight(x) (((x)<<2))                                   // x*4  = (x<<2)
#elif defined(LEDMatrixMode_K104_PWM)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_K104_PWM)    // PWM模式刷新LED测试矩阵
#define  LEDMatrixWidth   26
#define  LEDMatrixHeight  4
// 定义乘法运算用于节约算力
#define  MultipLEDMatrixWidth(y) (((y)<<4)+((y)<<3)+((y)<<1))                  // y*26 = y*(16+8+2) = (y<<4)+(y<<3)+(y<<1)
#define  MultipLEDMatrixHeight(x) (((x)<<2))                                   // x*4  = (x<<2)
#elif defined(LEDMatrixMode_4X32A)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_4X32A)    // 4*32 RGB 矩阵
#define  LEDMatrixWidth   32
#define  LEDMatrixHeight  4
// 定义乘法运算用于节约算力
#define  MultipLEDMatrixWidth(y)  ((y)<<5)                                     // y*32 = (y<<5)
#define  MultipLEDMatrixHeight(x) (((x)<<2))                                   // x*4  = (x<<2)
#elif defined(LEDMatrixMode_PWM8X14)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_PWM8X14)    // 8*14 模拟 PWM RGB 矩阵
#define  LEDMatrixWidth   14
#define  LEDMatrixHeight  8
// 定义乘法运算用于节约算力
#define  MultipLEDMatrixWidth(y)  (((y)<<3)+((y)<<2)+((y)<<1))                 // y*14 = 8*(8+4+2) = (y<<3)+(y<<2)+(y<<1)
#define  MultipLEDMatrixHeight(x) (((x)<<3))                                   // x*8  = (x<<3)
#elif defined(LEDMatrixMode_MEGACUBE8)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_MEGACUBE8)// 8个点光立方
#define  LEDMatrixWidth   64
#define  LEDMatrixHeight  8
#define  LEDMatrixZAxis   8
// 定义乘法运算用于节约算力
#define  MultipLEDMatrixWidth(y)  (((y)<<6))                 // y*64 = (y<<6)
#define  MultipLEDMatrixHeight(x) (((x)<<3))                 // x*8  = (x<<3)
#define  MultipLEDMatrixPos(x,y,z)    ((x)+((y)<<3)+((z)<<6))// x+y*8+z*64  = (x)+((y)<<3)+((z)<<6)
#elif defined(LEDMatrixMode_MUSIC)  && defined(LEDMatrixMode)  && (LEDMatrixMode==LEDMatrixMode_MUSIC)    // PWM模式刷新LED测试矩阵
#define  LEDMatrixWidth   5
#define  LEDMatrixHeight  5
// 定义乘法运算用于节约算力
#define  MultipLEDMatrixWidth(y)  (((y)<<2)+(y))                  // y*5= y*(4+1) = (y<<2)+y
#define  MultipLEDMatrixHeight(x) (((x)<<2)+(x))                                   // x*5 = (x<<2)+x
#else     // 未定义键盘类型
#error   "Please define LEDMatrixMode!!!"
#endif

extern void mled_draw_pixel(const int16_t x, const int16_t y, const uint32_t color);
extern void mega_draw_pixel(const int16_t x, const int16_t y, const int16_t z, const uint32_t color);
//extern void mled_draw_index(const uint16_t index, const uint32_t color);
//extern void mled_buffer(const uint8_t data[], const uint16_t size);
extern void mled_view_kb_direct_update(const uint8_t _data[], const uint16_t size);
extern uint32_t mled_get_pixel(const int16_t x, const int16_t y);
//extern const struct BRGB* mled_get_frame_buffer(void);
extern const uint32_t* mled_get_frame_buffer(void);
// It's good to implement those, even if using transaction API
// (x,y) is topmost point; if unsure, calling function
// should sort endpoints or call drawLine() instead
extern void mled_drawFastVLine(const int16_t x, const int16_t y, const uint16_t h, const uint32_t color);
// (x,y) is leftmost point; if unsure, calling function
// should sort endpoints or call drawLine() instead
extern void mled_drawFastHLine(const int16_t x, const int16_t y, const uint16_t w, const uint32_t color);
// 
extern void mled_fill_rect(const int16_t x, const int16_t y, const uint16_t w, const uint16_t h, const uint32_t color);
static inline void mled_fillScreen(const uint32_t color)
{
    // Update in subclasses if desired!
    mled_fill_rect(0, 0, LEDMatrixWidth, LEDMatrixHeight, color);
}

// public API
// 通过坐标获取点的数据索引
extern uint16_t pmXY(int16_t x, int16_t y, const uint16_t Width, const uint16_t Height);
//// 描点
//static inline void pmled_draw_pixel(uint32_t mLED[], const int16_t Width, const uint16_t Height, const int16_t x, const int16_t y, const uint32_t color) 
//{
//	mLED[pmXY(x,y, Width, Height)] = color;
//}
//// 获取像素点数据
//static inline uint32_t pmled_get_pixel(uint32_t mLED[], const int16_t Width, const uint16_t Height, const int16_t x, const int16_t y) 
//{
//	return mLED[pmXY(x,y, Width, Height)];
//}
extern void pmled_drawFastVLine(uint32_t mLED[], const uint16_t Width, const uint16_t Height, const int16_t x, const int16_t y, const uint16_t h, const uint32_t color);
extern void pmled_drawFastHLine(uint32_t mLED[], const int16_t Width, const uint16_t Height, const int16_t x, const int16_t y, const uint16_t w, const uint32_t color);
extern void pmled_fill_rect(uint32_t mLED[], const uint16_t Width, const uint16_t Height, const int16_t x, const int16_t y, const uint16_t w, const uint16_t h, const uint32_t color);
static inline void pmled_fillScreen(uint32_t mLED[], const int16_t Width, const uint16_t Height, const uint32_t color)
{
    // Update in subclasses if desired!
    pmled_fill_rect(mLED, Width, Height, 0, 0, Width, Height, color);
}
extern void mled_draw_RGB565_Bitmap(const int16_t x, const int16_t y, const uint16_t bitmap[], const int16_t w, const int16_t h);
extern void mled_draw_RGB888_Bitmap(const int16_t x, const int16_t y, const uint32_t bitmap[], const int16_t w, const int16_t h);
extern void mled_kb_draw_RGB565_Bitmap(const int16_t x, const int16_t y, const uint16_t bitmap[], const int16_t w, const int16_t h);
extern void mled_kb_draw_RGB888_Bitmap(const int16_t x, const int16_t y, const uint32_t bitmap[], const int16_t width, const int16_t height);
extern void mled_kb_mRight_draw_RGB888_Bitmap(const int16_t x, const int16_t y, const uint32_t bitmap[], const uint16_t width, const uint16_t height, const uint8_t dpi, const uint8_t grade);

#ifdef __cplusplus
}
#endif

#endif /* _CRGB_MATRIX_H_ */

